﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Lucene.Linq.Search;

namespace Lucene.Linq.VSTests
{
    [TestClass]
    public class TestSorting
    {
        #region populators

        private void IndexSamples(IIndex<Sample> idx, IEnumerable<Sample> samples)
        {
            idx.Add(samples);
            Assert.IsTrue(idx.Count == samples.Count());
        }

        private void IndexSamples(IIndex<Sample> idx, int num)
        {
            IndexSamples(idx, num, null);
        }

        private void IndexSamples(IIndex<Sample> idx, int num, Action<Sample> modifier)
        {
            idx.Add(SampleGenerator.GetRandom(num, modifier));
            Assert.IsTrue(idx.Count == num);
        }

        #endregion

        #region asserters

        //void AssertSamplesInOrder<TField>(IEnumerable<Sample> samples, Func<Sample,TField> func)
        //{
        //    AssertInOrder(samples,func,new SampleComparer<TField>(func));
        //}

        //void AssertInOrder<T>(IEnumerable<T> items, Comparison<T> comparison)
        //{
        //    var expected = items.ToList();
        //    expected.Sort(comparison);

        //    var actual = items.ToList();

        //    Assert.AreEqual(expected,actual,(a,b)=> comparison(a, b) == 0);
        //}

        //void AssertInOrder<T,TField>(IEnumerable<T> items, Func<T,TField> fieldSelector, IComparer<T> itemComparer) {
        //    var expected = items.OrderBy(fieldSelector).ToList();
        //    var actual = items.ToList();
        //    Assert.AreEqual(expected, actual, (a, b) => itemComparer.Compare(a, b) == 0);
        //}

        #endregion

        [TestMethod]
        [Description("just a test to see how linq to objects works with multi-sorting")]
        public void Simple_Multi_Sort_With_Linq_To_Objects()
        {
            var things = new[]
                             {
                                 new {A = 2, B = "d"},
                                 new {A = 1, B = "a"},
                                 new {A = 6, B = "f"},
                                 new {A = 2, B = "c"},
                                 new {A = 5, B = "e"},
                                 new {A = 2, B = "b"},
                             };


            var sorted = from t in things
                         orderby t.A, t.B
                         select t;

            foreach (var s in sorted)
            {
                Console.WriteLine("{0} {1}", s.A, s.B);
            }
        }


        [TestMethod]
        public void Sorting_By_Integer_Then_String_Ascending()
        {
            using (var i = new Index<Sample>())
            {
                var samples = new[]
                                  {
                                      new Sample {CaptainInteger = 3, MrString = "eee"},
                                      new Sample {CaptainInteger = 0, MrString = "bbb"},
                                      new Sample {CaptainInteger = 1, MrString = "ddd"},
                                      new Sample {CaptainInteger = 1, MrString = "ccc"},
                                      new Sample {CaptainInteger = 1, MrString = "a"},
                                      new Sample {CaptainInteger = 0, MrString = "aaaa"},
                                  };

                IndexSamples(i, samples);

                List<Sample> results = (from s in i
                                        orderby s.CaptainInteger, s.MrString
                                        select s).ToList();

                Assert.IsTrue(results.OrderBy(s => s.CaptainInteger).ThenBy(s => s.MrString).SequenceEqual(results));
            }
        }


        [TestMethod]
        public void Sorting_By_String_Ascending_With_Where_And_Select_Should_Not_Throw()
        {
            using (var i = new Index<Sample>())
            {
                IndexSamples(i, 10, (s) => s.MrString = "george");

                var results = (from s in i
                               where s.MrString == "george"
                               orderby s.MrString
                               select new
                                          {
                                              s.MrString
                                          }).ToList();
            }
        }

        [TestMethod]
        public void Sorting_By_String_Ascending()
        {
            using (var i = new Index<Sample>())
            {
                IndexSamples(i, 10);

                List<Sample> results = (from s in i
                                        orderby s.MrString
                                        select s).ToList();

                Assert.IsTrue(results.OrderBy(s => s.MrString).SequenceEqual(results));
            }
        }

        [TestMethod]
        public void Sorting_By_String_Descending()
        {
            using (var i = new Index<Sample>())
            {
                IndexSamples(i, 10);

                IOrderedQueryable<Sample> results = from s in i
                                                    orderby s.MrString descending
                                                    select s;

                Assert.IsTrue(Enumerable.SequenceEqual(results.OrderByDescending(s => s.MrString), results));
            }
        }

        [TestMethod]
        public void Sorting_By_Integer_Descending()
        {
            using (var i = new Index<Sample>())
            {
                IndexSamples(i, 10);

                IOrderedQueryable<Sample> results = from s in i
                                                    orderby s.CaptainInteger descending
                                                    select s;

                Assert.IsTrue(Enumerable.SequenceEqual(results.OrderByDescending(s => s.CaptainInteger), results));
            }
        }

        [TestMethod]
        public void Sorting_By_Integer_Ascending()
        {
            using (var i = new Index<Sample>())
            {
                IndexSamples(i, 10);

                IOrderedQueryable<Sample> results = from s in i
                                                    orderby s.CaptainInteger
                                                    select s;

                Assert.IsTrue(Enumerable.SequenceEqual(results.OrderBy(s => s.CaptainInteger), results));
            }
        }
    }
}